package BandB.Tool.GPhoneManager.TaskManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import BandB.Tool.GPhoneManager.R;
import BandB.Tool.GPhoneManager.TaskManager.Util.DataHandler;
import BandB.Tool.GPhoneManager.TaskManager.Util.Utilities;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class ProcessGrid extends Activity {

	private GridView proView;
	private TextView loadingView, memoryTextView, userTextView, systemTextView;

	private GridAdapter adapter;
	private static final int MSG_LOADING_END = 1;
	private static final int MSG_LOADING_START = 0;
	private static final int MSG_REFRESH_STATUS = -1;

	private static final byte MODE_SHOW_LOADING = 0;
	private static final byte MODE_SHOW_GRID = 1;
	protected static final String TAG = "ProcessGrid";
	private static ActivityManager activityManager;
	private Timer timerGetCache, timerGetStatus;
	private Process process = null;
	private static String status;
	private static final byte[] SYNC = new byte[0];

	public static final String NOTIFICATION_ACTION = "notification_action";

	private TimerTask taskGetCache, taskGetStatus;
	private DataHandler dataHandler;
	private static String available_memory, cpuUser, cpuSystem;
	private static LayoutInflater inflater;
	private static NotificationManager notificationManager;
	private static Notification noti;

	private static boolean do_not_ask = false;
	private static boolean pin_to_notificationBar = true;
	private static boolean always_show_in_notiBar = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
//		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.process_grid);
		Log.e(TAG, "create");
		initViewStatus();

		setShowMode(MODE_SHOW_LOADING);

		dataHandler = new DataHandler(this);
		inflater = LayoutInflater.from(this);

		activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		setNotificationAlwaysShow(false);
		mHandler.sendEmptyMessage(MSG_LOADING_START);

		if (ScheduleService.isFirstRunning()) {
			Log.i(TAG, "service is first time running.");
			ScheduleService.setRestart(true);
			startService(new Intent(this, ScheduleService.class));
		} else {
			Log.i(TAG, "service has been started.");
		}
		// com.mgeek.android.util.CheckUpdateService.checkUpdate(this);
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.e(TAG, "resume");
		timerGetCache = new Timer();
		taskGetCache = generateGetCacheTask();
		timerGetCache.schedule(taskGetCache, 0, 5000);

		timerGetStatus = new Timer();
		taskGetStatus = generateGetStatusTask();
		timerGetStatus.schedule(taskGetStatus, 1000, 5000);
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		Log.e(TAG, "pause");
		try {
			taskGetCache.cancel();
			timerGetCache.cancel();
			timerGetCache = null;

			taskGetStatus.cancel();
			timerGetStatus.cancel();
			taskGetStatus = null;
		} catch (Exception e) {
			// TODO: handle exception
			Log.e(TAG, "cancel tasks error:" + e.getMessage());
		}

		super.onPause();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		Log.e(TAG, "destroy");
		super.onDestroy();
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		switch (resultCode) {
		case TIME_SETTING:
			Log.i(TAG, "timesetting return");
			break;

		default:
			break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	private void setNotificationAlwaysShow(boolean show) {

		noti = new Notification(R.drawable.task_manager, "Task Manager", System
				.currentTimeMillis());
		// PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
		// new Intent(NOTIFICATION_ACTION), 0);
		PendingIntent pendingIntent = PendingIntent.getService(this, 0,
				new Intent(this, NotificationService.class), 0);
		noti.setLatestEventInfo(this, "Warning", "Terminate all processes",
				pendingIntent);

		if (show) {
			noti.flags = Notification.FLAG_NO_CLEAR;
		} else {
			noti.flags = Notification.FLAG_AUTO_CANCEL;
		}
		notificationManager.notify(NOTI_ID, noti);
	}

	private TimerTask generateGetCacheTask() {
		return new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					String cache = "";
					BufferedReader br = null;
					String cmd = "top -n 1";
					Runtime runtime = Runtime.getRuntime();
					process = runtime.exec(cmd);
					InputStream is = process.getInputStream();
					InputStreamReader isr = new InputStreamReader(is);
					br = new BufferedReader(isr);
					String line;
					while ((line = br.readLine()) != null) {
						cache += line + "\n";
					}
					synchronized (SYNC) {
						status = cache;
					}
				} catch (IOException e) {
					// TODO: handle exception
					e.printStackTrace();
					Log.e(TAG, "get status cathe string error.");
				}
			}
		};
	}

	private TimerTask generateGetStatusTask() {
		return new TimerTask() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				try {
					String cache = "";
					BufferedReader br = null;
					String cmd = "top -n 1";
					Runtime runtime = Runtime.getRuntime();
					process = runtime.exec(cmd);
					InputStream is = process.getInputStream();
					InputStreamReader isr = new InputStreamReader(is);
					br = new BufferedReader(isr);
					String line;
					while ((line = br.readLine()) != null) {
						cache += line + "\n";
					}
					synchronized (SYNC) {
						status = cache;
						String cpu = Utilities.getAllCpuUsage(status);
						Log.e(TAG, "cpu:" + cpu);
						Pattern pUser = Pattern.compile("User (.*?),");
						Pattern pSystem = Pattern.compile("System (.*?),");
						Matcher mUser = pUser.matcher(cpu);
						Matcher mSystem = pSystem.matcher(cpu);
						if (mUser.find()) {
							cpuUser = mUser.group(1);
						} else {
							cpuUser = "0%";
						}
						if (mSystem.find()) {
							cpuSystem = mSystem.group(1);
						} else {
							cpuSystem = "0%";
						}
						MemoryInfo outInfo = new MemoryInfo();
						activityManager.getMemoryInfo(outInfo);
						available_memory = Utilities
								.formateSize(outInfo.availMem);
						mHandler.sendEmptyMessage(MSG_REFRESH_STATUS);
					}
				} catch (IOException e) {
					// TODO: handle exception
					e.printStackTrace();
					Log.e(TAG, "get status cathe string error.");
				}
			}
		};
	}

	private void initViewStatus() {
		memoryTextView = (TextView) findViewById(R.id.txtViewMemory);
		userTextView = (TextView) findViewById(R.id.txtViewUser);
		systemTextView = (TextView) findViewById(R.id.txtViewSystem);
		proView = (GridView) findViewById(R.id.appsGrid);
		proView.setOnItemClickListener(gridItemClicklistener);
		loadingView = (TextView) findViewById(R.id.loadingText);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		MenuInflater menuInflater = getMenuInflater();
		try {
			menuInflater.inflate(R.menu.process_grid_menu, menu);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch (item.getItemId()) {
		case R.id.grid_item_refresh:
			mHandler.sendEmptyMessage(MSG_LOADING_START);
			break;
//		case R.id.grid_item_blacklist:
//			ArrayList<SimpleAppInfo> list = dataHandler
//					.getSimpleInfoOfBlacklist();
//			if (0 == list.size()) {
//				Toast.makeText(this, "No application exists in blacklist",
//						Toast.LENGTH_SHORT).show();
//			} else {
//				Intent intent = new Intent(this, BlacklistActivity.class);
//				startActivity(intent);
//			}
//			break;
		// case R.id.grid_item_about:
		// break;
//		case R.id.grid_item_list_view:
//			startActivity(new Intent(this, ProcessList.class));
//			break;
//		case R.id.grid_item_scheduler:
//			startActivityForResult(new Intent(this, TimeSetting.class),
//					TIME_SETTING);
//			break;
		case R.id.grid_item_settings:
			showSettingDialog();
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	private void showSettingDialog() {
		final Dialog settingDialog = new Dialog(this);
		settingDialog.setTitle("Settings");
		View view = inflater.inflate(R.layout.setting_view, null);
		settingDialog.setContentView(view);
		final CheckBox check_notification = (CheckBox) view
				.findViewById(R.id.appmanager_pin_check);
		check_notification.setChecked(pin_to_notificationBar);
		final CheckBox check_always_show_noti = (CheckBox) view
				.findViewById(R.id.setting_check_always_show);
		check_always_show_noti.setChecked(always_show_in_notiBar);
		check_notification
				.setOnCheckedChangeListener(new OnCheckedChangeListener() {

					@Override
					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {
						// TODO Auto-generated method stub
						if (!isChecked) {
							check_always_show_noti.setChecked(false);
							check_always_show_noti.setClickable(false);
						} else {
							check_always_show_noti.setChecked(false);
							check_always_show_noti.setClickable(true);
						}
					}
				});

		final CheckBox check_mention = (CheckBox) view
				.findViewById(R.id.check_mention);
		check_mention.setChecked(do_not_ask);

		Button btnConfirm = (Button) view.findViewById(R.id.confirm_button);
		Button btnCancel = (Button) view.findViewById(R.id.cancel_button);
		android.view.View.OnClickListener listener = new android.view.View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				switch (v.getId()) {
				case R.id.confirm_button:
					Log.e(TAG, "confirm clicked");
					do_not_ask = check_mention.isChecked();
					if (check_notification.isChecked()) {
						pin_to_notificationBar = true;
						if (check_always_show_noti.isChecked()) {
							always_show_in_notiBar = true;
							setNotificationAlwaysShow(true);
						} else {
							always_show_in_notiBar = false;
							setNotificationAlwaysShow(false);
						}
					} else {
						notificationManager.cancel(NOTI_ID);
						pin_to_notificationBar = false;
						always_show_in_notiBar = false;
					}
					settingDialog.dismiss();
					break;
				case R.id.cancel_button:
					Log.e(TAG, "cancel clicked");
					settingDialog.dismiss();
					break;

				default:
					break;
				}
			}
		};
		btnConfirm.setOnClickListener(listener);
		btnCancel.setOnClickListener(listener);

		settingDialog.show();
	}

	public static final int NOTI_ID = 64;
	public static final int TIME_SETTING = 100;

	private final OnItemClickListener gridItemClicklistener = new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			// TODO Auto-generated method stub
			Log.e(TAG, "" + arg2);
			final ApplicationInfo info = (ApplicationInfo) adapter
					.getItem(arg2);
			if (dataHandler.IsSystemProcess(info.appInfo.packageName)) {
				Toast.makeText(
						ProcessGrid.this,
						"Can't stop application: " + info.title
								+ ", it is a system process",
						Toast.LENGTH_SHORT).show();
				return;
			}
			if (do_not_ask) {
				try {
					activityManager.restartPackage(info.appInfo.packageName);
					mHandler.sendEmptyMessage(MSG_LOADING_START);
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
					Toast.makeText(
							ProcessGrid.this,
							"Can't stop application:"
									+ info.appInfo.packageName,
							Toast.LENGTH_SHORT).show();
				}
				return;
			}
			AlertDialog.Builder builder = new AlertDialog.Builder(
					ProcessGrid.this).setTitle("Warning").setIcon(
					R.drawable.ic_menu_notifications);
			View view = inflater.inflate(R.layout.grid_kill_process_dialog,
					null);
			TextView txtView = (TextView) view.findViewById(R.id.txtWhatToKill);
			txtView.setText("Continue to stop process: " + info.title + "?\n");
			final CheckBox grid_check_mention = (CheckBox) view
					.findViewById(R.id.grid_check_mention);
			grid_check_mention.setChecked(do_not_ask);
			builder.setView(view);
			builder.setPositiveButton(R.string.ok, new OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					try {
						do_not_ask = grid_check_mention.isChecked();
						activityManager
								.restartPackage(info.appInfo.packageName);
						mHandler.sendEmptyMessage(MSG_LOADING_START);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
						Toast.makeText(
								ProcessGrid.this,
								"Can't stop application:"
										+ info.appInfo.packageName,
								Toast.LENGTH_SHORT).show();
					}

				}
			});
			builder.setNegativeButton(R.string.cancel, new OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					Log.e(TAG, "" + "cancel");
				}
			});
			builder.show();
		}

	};

	private void setShowMode(byte mode) {
		switch (mode) {
		case MODE_SHOW_GRID:
			loadingView.setVisibility(View.GONE);
			proView.setVisibility(View.VISIBLE);
			break;
		case MODE_SHOW_LOADING:
			loadingView.setVisibility(View.VISIBLE);
			proView.setVisibility(View.GONE);
			break;
		default:
			break;
		}
	}

	private void refreshStatusBar() {
		memoryTextView.setText(available_memory);
		userTextView.setText(cpuUser);
		systemTextView.setText(cpuSystem);
	}

	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case MSG_LOADING_START:
				new Thread(new Runnable() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						ArrayList<ApplicationInfo> list = Utilities
								.getRunningAppList(ProcessGrid.this);
						adapter = new GridAdapter(ProcessGrid.this, list);
						mHandler.sendEmptyMessage(MSG_LOADING_END);
					}
				}).start();
				break;
			case MSG_LOADING_END:
				proView.setAdapter(adapter);
				setShowMode(MODE_SHOW_GRID);
				break;
			case MSG_REFRESH_STATUS:
				refreshStatusBar();
				break;
			default:
				break;
			}
			super.handleMessage(msg);
		}
	};
}
